
package jumpingnotes.service.remoting;

import java.util.Date;
import java.util.List;

import jumpingnotes.model.*;
import jumpingnotes.model.entity.Activity;
import jumpingnotes.model.entity.ActivityMediaItem;
import jumpingnotes.model.entity.ActivityTemplate;
import jumpingnotes.model.entity.ActivityTemplateParam;
import jumpingnotes.model.entity.Member;
import jumpingnotes.model.entity.MemberConfirm;
import jumpingnotes.model.entity.Message;
import jumpingnotes.util.MailHelper;

public class MemberServiceImpl extends GenericService implements MemberService{

	public static final String EMAIL_REGEX = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
	
	private MailHelper mailHelper;
	
	public MailHelper getMailHelper() {
		return mailHelper;
	}

	public void setMailHelper(MailHelper mailHelper) {
		this.mailHelper = mailHelper;
	}

	public Result memberRegister(String email, String password, String nickname)
	{
		Result chkEmail = isEmailUnique(email);
		if(chkEmail.isSuccess())
		{
			// save MemberConfirm
			MemberConfirm mc = new  MemberConfirm();
			mc.setCreateTime(new Date());
			mc.setEmail(email);
			mc.setPassword(password);
			mc.setNickname(nickname);
			int memberConfirmId = accessService.saveMemberConfirm(mc);
			
			// sendEmail
			System.out.println(mc.getMemberConfirmId());
			this.getMailHelper().sendEmail(email, "Registration Activation!", "http://www.readjoy.cn/jumpingNotes/activate?id="+memberConfirmId);
			return new Result(new Integer(memberConfirmId));
		}
		else 
			return new Result(ErrorType.USER_EMAIL_EXIST);
	}
	
	public Result isEmailUnique(String email)
	{
		if (email == null || email.trim().length() == 0 || !email.trim().matches(EMAIL_REGEX))
			return new Result(ErrorType.INVALID_EMAIL);
		
		// check whether email is unique in member
		Member exampleMember = new Member();
		exampleMember.setEmail(email);
		List<Member> memberList = accessService.findAllMember(exampleMember);
		boolean uniqueInMember = memberList != null && memberList.size() == 0;

		// check whether email is unique in member confirm
		MemberConfirm exampleMemberConfirm = new MemberConfirm();
		exampleMemberConfirm.setEmail(email);
		List<MemberConfirm> memberConfirmList = accessService.findAllMemberConfirm(exampleMemberConfirm);
		boolean uniqueInMemberConfirm = memberConfirmList != null && memberConfirmList.size() == 0;

		if(uniqueInMember && uniqueInMemberConfirm)
			return new Result();
		else
			return new Result(ErrorType.DUPLICATE_EMAIL);
	}
	
	public Result isPasswordCorrect(String memberID, String password)
	{
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member == null)
			return new Result(ErrorType.USER_NOT_EXIST);
		else if(password.equals(member.getHashedPassword()))
			return new Result();
		else
			return new Result(ErrorType.PASSWORD_MISMATCH);
	}
	
	public Result memberLogin(String email, String password)
	{
		if (email == null || email.trim().length() == 0 || !email.trim().matches(EMAIL_REGEX))
			return new Result(ErrorType.INVALID_EMAIL);

		Member exampleMember = new Member();
		exampleMember.setEmail(email);
		List<Member> memberList = accessService.findAllMember(exampleMember);

		// find the user
		if (memberList != null && memberList.size() == 1)
		{
			Member member = memberList.get(0);

			// check password
			if (password != null && password.equals(member.getHashedPassword()))
			{
				// login successful - update last login time
				if (member.getAccessTime() != null) {
					member.setLastLoginTime(member.getAccessTime());					
				} else {
					member.setLastLoginTime(new Date());
				}
				member.setAccessTime(new Date());
				accessService.updateMember(member);
				return new Result();
			}
			else
				return new Result(ErrorType.PASSWORD_MISMATCH);
		}
		else
			return new Result(ErrorType.USER_NOT_EXIST);

	}
	
	public Result memberLogout(String email, String password)
	{
		return new Result();
	}
	
	public Result memberRegisterInvite(String email, String memberID)
	{
		// do some check
		Result chkEmail = isEmailUnique(email);
		if(chkEmail.isSuccess())
		{
			// save MemberConfirm
			MemberConfirm mc = new  MemberConfirm();
			mc.setCreateTime(new Date());
			mc.setEmail(email);
			mc.setMemberIdInvite(Integer.parseInt(memberID));
			accessService.saveMemberConfirm(mc);
			// sendEmail
			System.out.println(mc.getMemberConfirmId());
			return new Result();
		}
		else
			return chkEmail;
	}
	
	public Result memberRegisterActivate(String email, String password)
	{
		MemberConfirm exampleMemberConfirm = new MemberConfirm();
		exampleMemberConfirm.setEmail(email);
		exampleMemberConfirm.setPassword(password);
		List<MemberConfirm> memberConfirmList = accessService.findAllMemberConfirm(exampleMemberConfirm);
		if(memberConfirmList.size() > 0)
		{
			MemberConfirm mc = memberConfirmList.get(0);
			Date now = new Date();
			Member member = new Member();
			member.setEmail(email);
			member.setHashedPassword(password);
			//set nickname
			member.setNickName(mc.getNickname());
			
			member.setAccessTime(now);
			member.setCreateTime(now);
			member.setUpdateTime(now);
			member.setLastLoginTime(now);
			accessService.saveMember(member);
			accessService.deleteMemberConfirm(mc);
			return new Result();
		}
		else
			return new Result(ErrorType.INVALID_CONFIRM_EMAIL);
	}
	
	public Result memberRegisterInviteActivate(String email, String password)
	{
		MemberConfirm exampleMemberConfirm = new MemberConfirm();
		exampleMemberConfirm.setEmail(email);
		List<MemberConfirm> memberConfirmList = accessService.findAllMemberConfirm(exampleMemberConfirm);
		if(memberConfirmList.size() > 0)
		{
			MemberConfirm mc = memberConfirmList.get(0);
			Member member = new Member();
			member.setEmail(email);
			member.setHashedPassword(password);
			//set MemberIdInvite
			member.setMemberIdInvite(mc.getMemberIdInvite());
			member.setNickName("");
			
			member.setAccessTime(new Date());
			member.setCreateTime(new Date());
			member.setUpdateTime(new Date());
			member.setLastLoginTime(new Date());
			accessService.saveMember(member);
			accessService.deleteMemberConfirm(mc);
			return new Result();
		}
		else
			return new Result(ErrorType.INVALID_CONFIRM_EMAIL);
	}

	public Result memberRegisterActivate(String memberConfirmId)
	{
		MemberConfirm mc = accessService.findMemberConfirmById(Integer.parseInt(memberConfirmId));
		if(mc != null)
		{
			Date now = new Date();
			Member member = new Member();
			member.setEmail(mc.getEmail());
			member.setHashedPassword(mc.getPassword());
			//set nickname
			member.setNickName(mc.getNickname());
			
			member.setAccessTime(now);
			member.setCreateTime(now);
			member.setUpdateTime(now);
			member.setLastLoginTime(now);
			accessService.saveMember(member);
			accessService.deleteMemberConfirm(mc);
			return new Result();
		}
		else
			return new Result(ErrorType.INVALID_CONFIRM_EMAIL);
	}	
	
	public Result memberPasswordUpdate(String memberID, String password)
	{
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member != null)
		{
			member.setUpdateTime(new Date());
			member.setHashedPassword(password);
			//set update time
			accessService.updateMember(member);
			return new Result();
		}
		else
			return new Result(ErrorType.USER_NOT_EXIST);
	}
	
	public Result memberPortraitUpload(String memberID, String image,
			String imageBig, String imageSmall, String imageSquare)
	{
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member != null)
		{
    		member.setImage(image);
    		member.setImageBig(imageBig);
    		member.setImageSmall(imageSmall);
    		member.setImageSquare(imageSquare);
    		member.setUpdateTime(new Date());
    		accessService.updateMember(member);
    		
    		// MEMBER_PORTRAIT_UPDATE activity
    		ActivityTemplateParam[] activityParams = new ActivityTemplateParam[1];
    		activityParams[0] = new ActivityTemplateParam();
    		activityParams[0].setName("member");
    		activityParams[0].setValue(member.getMemberId()+"&"+member.getNickName());
    		ActivityMediaItem[] mediaItems = new ActivityMediaItem[1];
    		mediaItems[0] = new ActivityMediaItem();
    		mediaItems[0].setMimeType(String.valueOf(ResourceTypes.TYPE_IMAGE));
    		mediaItems[0].setUrl(image);
    		memberActivityCreate(memberID,ActivityType.MEMBER_PORTRAIT_UPDATE,activityParams,mediaItems,null,"1");
    		// end MEMBER_PORTRAIT_UPDATE activity
    		
    		return new Result();
		}
		else 
			return new Result(ErrorType.USER_NOT_EXIST);
	}
	
	public Result memberInfoUpdate(String memberID, String nickname, String aboutMe, String birthday,
			Character gender, String locationCity, String locationProvince, String locationCountry, String homepage)
	{
		Member member = accessService.findMemberById(Integer.parseInt(memberID));
		if(member != null)
		{
			member.setNickName(nickname);
			member.setAboutMe(aboutMe);
			member.setBirthday(birthday);
			member.setGender(gender);
			member.setLocationCity(locationCity);
			member.setLocationProvince(locationProvince);
			member.setLocationCountry(locationCountry);
			member.setHomepage(homepage);
			// set update time
			member.setUpdateTime(new Date());
			accessService.updateMember(member);
			
			// Create memberUpdate activity
    		ActivityTemplateParam[] activityParams = new ActivityTemplateParam[1];
    		activityParams[0] = new ActivityTemplateParam();
    		activityParams[0].setName("member");
    		activityParams[0].setValue(member.getMemberId() + "&" + member.getNickName());
    		memberActivityCreate(memberID, ActivityType.MEMBER_INFO_UPDATE, activityParams, null, null, "1");
 			
			return new Result();
		}
		else
			return new Result(ErrorType.USER_NOT_EXIST);
	}
	
	public Result messageSend(String memberIDFrom, String memberIDTo, String title, String body)
	{
		// do check
		Member sender = accessService.findMemberById(Integer.parseInt(memberIDFrom));
		if(sender == null)
			return new Result();
		Member receiver = accessService.findMemberById(Integer.parseInt(memberIDTo));
		if(receiver == null)
			return new Result();
		Message message = new Message();
		message.setMemberByMemberIdFrom(sender);
		message.setMemberByMemberIdTo(receiver);
		message.setSubject(title);
		message.setBody(body);
		message.setCreateTime(new Date());
		message.setIsRead(0);
		message.setIsDeletedFrom(0);
		message.setIsDeletedTo(0);
		accessService.saveMessage(message);
		return new Result();
	}
	
	public Result messageDelete(String memberID, String [] messageIDArray)
	{
		int intMemberID = Integer.parseInt(memberID);
		if(messageIDArray != null)
		{
    		for(int i=0; i<messageIDArray.length; i++)
    		{
    			Message message = accessService.findMessageById(Integer.parseInt(messageIDArray[i]));
    			if(message != null)
    			{
    				if(message.getMemberByMemberIdFrom().getMemberId().equals(intMemberID))
    				{
    					message.setIsDeletedFrom(1);
    					accessService.updateMessage(message);
    				}
    				if(message.getMemberByMemberIdTo().getMemberId().equals(intMemberID))
    				{
    					message.setIsDeletedTo(1);
    					accessService.updateMessage(message);
    				}
    				
    				// if the message is deleted both by sender and receiver, message will be eliminated from the DB
    				if(message.getIsDeletedFrom() == 1 && message.getIsDeletedTo() == 1)
    				{
    					accessService.deleteMessage(message);
    				}
    			}
    		}
    		return new Result();
		}
		else
			return new Result(ErrorType.MESSAGE_NOT_EXIST);
	}

	@Override
	public Result memberPasswordRetrieve(String email) {
		// TODO Auto-generated method stub
		Member exampleMember = new Member();
		exampleMember.setEmail(email);
		List<Member> memberList = accessService.findAllMember(exampleMember);
		if (memberList.get(0) == null) {
			return new Result(ErrorType.USER_NOT_EXIST);
		}	
		mailHelper.sendEmail(email, "Your password@readjoy.cn retrieved!", memberList.get(0).getHashedPassword());
		return new Result(ErrorType.NO_ERROR);
	}

}
